/*
 * Licensed to Jasig under one or more contributor license
 * agreements. See the NOTICE file distributed with this work
 * for additional information regarding copyright ownership.
 * Jasig licenses this file to you under the Apache License,
 * Version 2.0 (the "License"); you may not use this file
 * except in compliance with the License.  You may obtain a
 * copy of the License at the following location:
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
package org.jasig.cas.client.session;

import org.jasig.cas.client.MySessionContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.CollectionUtils;

import javax.servlet.http.HttpSession;
import java.util.*;

/**
 * HashMap backed implementation of SessionMappingStorage.
 *
 * @author Scott Battaglia
 * @version $Revision$ $Date$
 * @since 3.1
 *
 */
public final class HashMapBackedSessionMappingStorage implements SessionMappingStorage {

    /**
     * Maps the ID from the CAS server to the Session.
     */
    private final Map<String, HttpSession> MANAGED_SESSIONS = new HashMap<String, HttpSession>();

    /**
     * Maps the Session ID to the key from the CAS Server.
     */
    private final Map<String, String> ID_TO_SESSION_KEY_MAPPING = new HashMap<String, String>();

    private final Logger logger = LoggerFactory.getLogger(getClass());

    public synchronized void addSessionById(String mappingId, HttpSession session) {
        ID_TO_SESSION_KEY_MAPPING.put(session.getId(), mappingId);
        MANAGED_SESSIONS.put(mappingId, session);

    }

    public synchronized void removeBySessionById(final String sessionId) {
        logger.debug("Attempting to remove Session=[{}]", sessionId);

        final String key = ID_TO_SESSION_KEY_MAPPING.get(sessionId);

        if (logger.isDebugEnabled()) {
            if (key != null) {
                logger.debug("Found mapping for session.  Session Removed.");
            } else {
                logger.debug("No mapping for session found.  Ignoring.");
            }
        }
        MANAGED_SESSIONS.remove(key);
        ID_TO_SESSION_KEY_MAPPING.remove(sessionId);
    }

    public synchronized HttpSession removeSessionByMappingId(String mappingId) {
        final HttpSession session = MANAGED_SESSIONS.get(mappingId);

        if (session != null) {
            //清除其他session
            removeOtherSession(mappingId, session.getId());

            removeBySessionById(session.getId());
        }

        return session;
    }

    private void removeOtherSession(String mappingId, String sessionId) {
        if (!CollectionUtils.isEmpty(ID_TO_SESSION_KEY_MAPPING)) {
            Set<Map.Entry<String, String>> entrySet = ID_TO_SESSION_KEY_MAPPING.entrySet();
            try {
                Iterator<Map.Entry<String, String>> iterator = entrySet.iterator();
                List<HttpSession> sessionList = null;
                while (iterator.hasNext()) {
                    Map.Entry<String, String> next = iterator.next();
                    if (next.getValue().equals(mappingId) && !next.getKey().equals(sessionId)) {
                        if (sessionList == null) {
                            sessionList = new ArrayList<>();
                        }
                        sessionList.add(MySessionContext.getSession(next.getKey()));
                    }
                }
                if (!CollectionUtils.isEmpty(sessionList)) {
                    sessionList.forEach(HttpSession::invalidate);
                }
               /* entrySet.forEach((e) -> {
                    if (e.getValue().equals(mappingId) && !e.getKey().equals(sessionId)) {
                        HttpSession session = MySessionContext.getSession(e.getKey());
                        session.invalidate();
                    }
                });*/
            } catch (Exception e) {
                logger.error("remove other session error", e);
            }

        }
    }
}
